﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace GCELibrary.Current
{
    /// <summary>
    /// 描述特性类型，用于对数据类型或成员进行说明
    /// </summary>
    [AttributeUsage(AttributeTargets.All)]
    public class DescriptionAttribute : Attribute
    {
        /// <summary>
        /// 描述信息
        /// </summary>
        public string Description { get;  set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 默认值
        /// </summary>
        public object DefaultValue { get; set; }
        /// <summary>
        /// 获取指定对象类型的描述信息
        /// </summary>
        /// <param name="value">要获取描述信息的对象</param>
        /// <returns>对象类型的描述信息</returns>
        public static DescriptionAttribute GetDescription(object value)
        {
            return GetDescription(value.GetType(), DescriptionObjectType.Type, null, false);
        }
        /// <summary>
        /// 获取指定类型的描述信息
        /// </summary>
        /// <param name="attributeType">要获取描述信息的类型</param>
        /// <returns>类型的描述信息</returns>
        public static DescriptionAttribute GetDescription(Type attributeType)
        {
            return GetDescription(attributeType, DescriptionObjectType.Type, null, false);
        }
        /// <summary>
        /// 获取指定类型的描述信息
        /// </summary>
        /// <param name="attributeType">要获取描述信息的类型</param>
        /// <param name="inherit">是否搜索继承类型</param>
        /// <returns>类型的描述信息</returns>
        public static DescriptionAttribute GetDescription(Type attributeType, bool inherit)
        {
            return GetDescription(attributeType, DescriptionObjectType.Type, null, inherit);
        }
        /// <summary>
        /// 获取指定类型的描述信息
        /// </summary>
        /// <param name="attributeType">要获取描述信息的类型</param>
        /// <param name="objectType">被描述对象类型枚举</param>
        /// <param name="name">名称</param>
        /// <returns>描述信息</returns>
        public static DescriptionAttribute GetDescription(Type attributeType, DescriptionObjectType objectType, string name)
        {
            return GetDescription(attributeType, objectType, name, false);
        }
        /// <summary>
        /// 获取指定类型的描述信息
        /// </summary>
        /// <param name="attributeType">要获取描述信息的类型</param>
        /// <param name="objectType">被描述对象类型枚举</param>
        /// <param name="name">名称</param>
        /// <param name="inherit">是否搜索继承类型</param>
        /// <returns>描述信息</returns>
        public static DescriptionAttribute GetDescription(Type attributeType, DescriptionObjectType objectType, string name, bool inherit)
        {
            MemberInfo memberInfo = null;
            object[] attributeArr = null;
            Type typeSource = typeof(DescriptionAttribute);
            switch (objectType)
            {
                case DescriptionObjectType.Event:
                    memberInfo = attributeType.GetEvent(name);
                    break;
                case DescriptionObjectType.Field:
                    memberInfo = attributeType.GetField(name);
                    break;
                case DescriptionObjectType.Method:
                    memberInfo = attributeType.GetMethod(name);
                    break;
                case DescriptionObjectType.Property:
                    memberInfo = attributeType.GetProperty(name);
                    break;
            }
            if (DescriptionObjectType.Type == objectType)
                attributeArr = attributeType.GetCustomAttributes(typeSource, inherit);
            else
                attributeArr = memberInfo.GetCustomAttributes(typeSource, inherit);
            if (attributeArr != null && attributeArr.Length > 0)
            {
                return ((DescriptionAttribute)(attributeArr[0]));
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 获取枚举类型的描述信息，
        /// </summary>
        /// <param name="value">value类型必须为枚举类型</param>
        /// <returns></returns>
        public static DescriptionAttribute GetEnumDescription(object value)
        {
            var type=value.GetType();
            if (!type.IsEnum)
                throw new ArgumentNullException("参数类型必须为枚举类型");
            var valueArr = value.ToString().Split(',');
            IList<DescriptionAttribute> result = new List<DescriptionAttribute>();
            foreach (var v in valueArr)
            {
                if (v.Trim() != "")
                {
                    var fi = type.GetField(v.Trim());
                    if (fi != null)
                    {
                        if (fi.GetCustomAttributes(typeof(AuxiliaryFieldAttribute), true).Length == 0)
                        {
                            var objs = fi.GetCustomAttributes(typeof(DescriptionAttribute), true);
                            if (objs.Length > 0)
                                result.Add((DescriptionAttribute)objs[0]);
                        }
                    }

                }
            }
            if (result.Count > 1)
            {
                DescriptionAttribute da = new DescriptionAttribute();
                int i = 0;
                foreach (var r in result)
                {
                    if (i == 0)
                        da = r;
                    else
                        da.Name+=","+r.Name;
                    i++;
                }
                return da;
            }
            else if (result.Count > 0)
            {
                return result[0];
            }
            else
            {
                return null;
            }
        }
        
        public override string ToString()
        {
            return Name;
        }
    }
    /// <summary>
    /// 被描述对象类型枚举
    /// </summary>
    public enum DescriptionObjectType
    {
        /// <summary>
        /// 事件
        /// </summary>
        Event = 1,
        /// <summary>
        /// 方法
        /// </summary>
        Method = 2,
        /// <summary>
        /// 字段
        /// </summary>
        Field = 4,
        /// <summary>
        /// 类型
        /// </summary>
        Property = 8,
        /// <summary>
        /// 类型
        /// </summary>
        Type = 16
    }
    
    /// <summary>
    /// 辅助字段，该特性用在枚举成员上面，用来标识该成员是不起作用
    /// </summary>
    [AttributeUsage(AttributeTargets.Enum|AttributeTargets.Field)]
    public class AuxiliaryFieldAttribute : Attribute
    {

    }
}
